﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using ServiceStack.Redis.Generic;
using LightSO.ILibrary;
using LightSO.Library.Common;
using LightSO.ILibrary.Mapping;

namespace LightSO.Library.Redis
{
    /// <summary>
    /// 基于Rides的数据仓储类实现
    /// </summary>
    /// <author>linlurui</author>
    public class Repository<T> : IRedisRepository<T> where T : EntityBase, new()
    {
        private string _collectionName = string.Empty;
        private SerializerHelper serializer;

        public Repository()
        {
            var _att = Attribute.GetCustomAttribute(typeof(T), typeof(RedisIdAttribute), true);
            string _collectionName = _att != null ? ((RedisIdAttribute)_att).Name : typeof(T).Name;
            serializer = new SerializerHelper();
        }
        public Repository(string collectionName)
        {
            _collectionName = collectionName;
            serializer = new SerializerHelper();
        }

        /// <summary>
        /// 根据主键获取类型为T的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">主键字段值</param>
        /// <returns></returns>
        public T Get(string id)
        {
            DbContext<T> db = new DbContext<T>();
            return db.Database.As<T>().GetValue(id.ToString());
        }
        /// <summary>
        /// 根据主键获取类型为T的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">主键字段值</param>
        /// <returns></returns>
        public string Get(string id, string defaultValue)
        {
            DbContext<T> db = new DbContext<T>();
            var result = db.Database.As<string>().GetValue(id.ToString());
            if (result == null)
                result = defaultValue;

            return result;
        }

        /// <summary>
        /// 根据主键获取类型为T的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">主键字段值</param>
        /// <returns></returns>
        public void Set(object id, T item)
        {
            DbContext<T> db = new DbContext<T>();
            db.Database.As<T>().GetAndSetValue(id.ToString(), item);
        }

        /// <summary>
        /// 根据主键获取类型为T的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">主键字段值</param>
        /// <returns></returns>
        public void Set(object id, string value)
        {
            DbContext<T> db = new DbContext<T>();
            db.Database.As<string>().GetAndSetValue(id.ToString(), value);
        }

        /// <summary>
        /// 入队
        /// </summary>
        public void Enqueue(string key, T t)
        {
            DbContext<T> db = new DbContext<T>();
            var redisDB = db.Database.As<T>();
            redisDB.EnqueueItemOnList(redisDB.Lists[key], t);
        }

        /// <summary>
        /// 入队
        /// </summary>
        public void Enqueue(string key, string value)
        {
            DbContext<T> db = new DbContext<T>();
            db.Database.EnqueueItemOnList(key, value);
        }

        /// <summary>
        /// 出队
        /// </summary>
        /// <typeparam name="T"><peparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public T Dequeue(string key)
        {
            DbContext<T> db = new DbContext<T>();
            var redisDB = db.Database.As<T>();
            return redisDB.DequeueItemFromList(redisDB.Lists[key]);
        }

        /// <summary>
        /// 出队
        /// </summary>
        /// <typeparam name="T"><peparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public string Dequeue(string key, string defaultValue = "")
        {
            DbContext<T> db = new DbContext<T>();
            var result = db.Database.DequeueItemFromList(key);
            if (result == null)
                result = defaultValue;

            return result;
        }

        /// <summary>
        /// 设置Hash值
        /// </summary>
        /// <param name="hashId">表名</param>
        /// <param name="key">key</param>
        /// <param name="values">存储对象</param>
        /// <returns>true or false</returns>
        public bool SetHash(string hashId, string key, T values)
        {
            DbContext<T> db = new DbContext<T>();
            return db.Database.SetEntryInHash(hashId, key, serializer.ToJson(values));
        }

        /// <summary>
        /// 设置Hash值
        /// </summary>
        /// <param name="hashId">表名</param>
        /// <param name="key">key</param>
        /// <param name="values">存储对象</param>
        /// <returns>true or false</returns>
        public bool SetHash(string hashId, string key, string values)
        {
            DbContext<T> db = new DbContext<T>();
            return db.Database.SetEntryInHash(hashId, key, values);
        }

        /// <summary>
        /// 获取hash值
        /// </summary>
        /// <param name="hashId">表名</param>
        /// <param name="key">key</param>
        /// <param name="values">存储对象</param>
        /// <returns></returns>
        public T GetHash(string hashId, string key)
        {
            DbContext<T> db = new DbContext<T>();
            return serializer.ConvertTo<string, T>(db.Database.GetValueFromHash(hashId, key));
        }

        /// <summary>
        /// 获取hash值
        /// </summary>
        /// <param name="hashId">表名</param>
        /// <param name="key">key</param>
        /// <param name="values">存储对象</param>
        /// <returns></returns>
        public string GetHash(string hashId, string key, string defaultValue = "")
        {
            DbContext<T> db = new DbContext<T>();
            var result = db.Database.GetValueFromHash(hashId, key);
            if (result == null)
                result = defaultValue;

            return result;
        }
    }
}
